브라우저 Viewport Interop 2022
개요
- 현재 Viewport 웹 명세 관련 정의 및 설명 살펴보기
- 현재 Viewport 웹 명세의 문제점
- 어떤 조치가 이뤄지고 있는지와 그 대안
Viewport 용어 및 개념 정리
The Viewport
- 유저가 문서와 상호작용할 수 있도록 문서가 보여지는 영역
- 클래식 스크롤바(스크롤바가 오버레이되지 않는 경우)를 제외한 화면상 보이는 영역
- 문서의 크기보다 Viewport가 작을 경우 스크롤을 지원해야한다.
- 지금은 Viewport의 종류가 많아져서 그냥 The Viewport라고 하는 것이 무엇인지 모호해졌다.
- 예전의 The Viewport는 The Layout Viewport로 새로운 명칭이 붙게 되었다.
The Layout Viewport
position: fixed
를 이용하여 뭔가를 배치했을 때 보여지는 영역- 스크롤시 따라다닌다.
- 자료 원작자는 The Position Fixed Viewport라고 이름 지었었어야하는 것 아닌가하고 농담을 한다.
Containing Block
- CSS에서는 DOM요소의 상자영역의 크기나 위치를 계산할 때 바깥 Containing Block의 테두리를 기준으로 한다.
- 계산된 상자 영역은 다시금 해당 요소의 자식의 상자영역을 계산하는 기준 Containing Block이 된다.
- 그렇다면 가장 처음에 배치될 때 기준이 되는 Containing Block은 뭘까?
아래 문서에서 각 요소의 Containing Block을 살펴보자
<!DOCTYPE html>
<html lang="en">
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>
</html>
<div class="child"></div>
의 Containing Block은 <div class="parent">...</div>
이다.<div class="parent">...</div>
의 Containing Block은 <body>...</body>
이다.<body>...</body>
의 Containing Block은 rootElement
혹은 documentElement
혹은 <html>...</html>
- 그럼
<html>...</html>
은?
The Initial Containing Block(ICB)
- ICB는
documentElement
의 Containing Block이다. - 크기는 layout viewport의 너비와 높이로 설정되며, 위치는 좌,상(0,0)을 기준으로 배치된다.
- 스크롤바 영역을 포함하지 않는다. 즉, 스크롤바가 생기면 크기가 줄어든다.
- 데스크탑의 경우 ICB와 layout viewport는 서로 크기가 같다. 왜 같은 영역을 표현하는 개념이 두개일까?
- 빨간색이 ICB, 파란색이 Layout Viewport이다.
- 문서를 아래로 스크롤 하는 경우,
- ICB는 0,0에 고정되어있기 때문에 보여지는 영역 밖에 위치하게된다.
- Layout Viewport는 따라온다.
- ICB의 크기를 알고 싶으면 어떤 API를 사용해야할까?
document.documentElement.clientWidth / clientHeight
를 이용해야한다.getBoundingClientRect()
는 containing block의 스타일이 적용 후 계산된 값이라서 width/height에 100% 값이 없으면 제대로 나오지 않는다.window.width / height
는 어떤 브라우저에서는 pinch zoom 하면 값이 바뀐다.
Viewport units
- CSS에서
v*
는 ICB를 기준으로 한 Viewport의 비율 크기 단위이다. vw, vh, vi, vb, vmin, vmax
가 있다.- 수직 스크롤바가 있을 때
width: 100vw
를 주면 수평 스크롤이 생긴다. - 스펙에 vw계산시 scrollbar는 없다고 가정하기 때문이다.
- 개발자들이 화났다
Pinch-zoom 할 때 ICB, Layout Viewport
- 아래와 같은 상태에서
- 아래로 스크롤을 했다고 가정하자.
- 빨간 영역은 ICB,
- 파란 영역은 Layout Viewport,
- 노란 점선은 우리에게 보여지는 영역(Visual Viewport)이라 하자
- Pinch zoom-in을 하면 아래와 같은 상태일 것이다.
- Visual Viewport는 Layout Viewport안에 담긴다.
- Zoom상태에서 스크롤 했을때 화면에 snap되는 경험을 해봤을 것이다.
- Visual Viewport가 Layout Viewport 바깥으로 가지 않으면 실제 윈도우 스크롤은 발생하지 않는다.
- 즉, Visual Viewport는 자신만의 scale과 scroll 상태를 가진다.
Visual Viewport API
window.visualViewport
로 사용 가능하다.
width / height
: Visual Viewport의 너비와 높이offsetTop / offsetLeft
: Visual Viewport에서 Layout Viewport까지의 거리 (좌, 상 기준)pageTop / pageLeft
: Visual Viewport에서 ICB까지의 거리 (좌, 상 기준)scale
: 확대 축소 비율
mobile에선 어떨까?
아래 브라우저(user-agent)의 Viewport는 어떻게 될까? (사파리, 크롬, 파이어폭스)
Layout Viewport
ICB
Visual Viewport
그런데 만약 페이지가 위 아래로 길 때 아래로 스크롤하면 어떻게 될까?
이런식으로 상단 하단의 UI가 감춰지게 된다.
UI가 나타나고 감춰지는 방식은 브라우저마다 다르다.
이때 Layout Viewport, ICB, Visual Viewport 영역은 어떻게 될까?
Layout Viewport
ICB는 초기 값이기 때문에 위치도 고정이고 크기도 바뀌지 않는다.
Visual Viewport는 UI가 사라진 영역만큼 확장된다.
The Large, Small and Dynamic Viewport
- 그렇다면
vh
값은 어떻게 되나? - 아까 분명 viewport unit은 ICB를 기준으로 한다고 했는데 왜 이렇지?
- 모바일 사파리가 먼저 저렇게 했고 결국엔 모두 저렇게 통일하게 되었다.
vh
는 툴바를 없는 것으로 가정한 크기로 측정- 그래서 스크롤을 내려서 UI가 사라지면 딱 맞게 된다.
- 그렇다면 모바일의 경우 viewport가 사실상 두종류이다.
- The Small Viewport: dynamic user agent interfaces(브라우저 UI) 가 보일 때 = ICB
sv*
: svh, svw, svmin, svmax, svi, svb
- The Large Viewport: 브라우저 UI 숨겨졌을 때 = ICB + 브라우저 UI 크기
- `lv*`: `lvh, lvw, lvmin, lvmax, lvi, lvb`
- Dynamic Viewport:
dv*
값이 언제 적용되는지는 브라우저가 UI를 어떤 메커니즘으로 숨기고 보여지냐에 따라 다름dvh, dvw, dvmin, dvmax, dvi, dvb
- 지금 chroimium은 feature flag로 사용 가능하고 파이어폭스와 사파리는 지원함
Resize Behavior
- 여기부터 고통이 시작된다.
- 아래는 ICB다.
- 가상키보드가 등장하면?
- 사파리를 제외하고 ICB가 변경된다. 초기값이니까 바뀌면 안되지 않나 싶으나... 현 상황은 이렇다.
- 이 자료를 만든 사람도 초기값이기 때문에 변하지 않는게 좋지 않을까라고 의견을 제시한다.
- 위처럼 ICB 크기는 Viewport unit에도 영향을 끼친다.
- 때문에 Chromium에선 논의가 더 필요하다 보고 아직 새로운 Viewport Unit을 제공하지 않는다.
- Layout Viewport를 살펴보면 상황이 비슷하다.
position: fixed
요소의 위치가 어떻게 되는지 보자.- 어떤게 더 나을까? 두 방식 모두 사용처가 있어 중립의 입장을 취한다.
- 만약 floating button을 만들고 싶다. 그러면 오른쪽과 같이 키패드가 올라오면서 키패드 위 영역부터 버튼이 표시되길 원할 것이다.
- 만약 nav bar을 만들고 싶다. 그러면 왼쪽 처럼 키패드가 오버레이 되길 원할 것이다.
Virtual Keyboard API
- 현재 Chroium만 지원한다.
- 다른 vendor는 API에 동의하지 않았다.
- 예를 들어 하나 말해보자면 키보드 숨김/보임을 API로 할 수 있다는 스펙에 동의하지 않았다.
- API 예시를 하나 살펴보자
if ("virtualKeyboard" in navigator) {
const vk = navigator.virtualKeyboard;
vk.overlaysContent = true;
vk.addEventListener('geometrychange', () => {
console.log(vk.boundingRect);
});
}
overlaysContent
: 가상키보드가 보일 때 ICB와 Layout Viewport를 Resize하지 않음. - 아직 자바스크립트로만 이 기능을 활성화할 수 있다. 그래서 이슈를 제의한 상태이다.
geometrychange
: 가상키보드 변형시 호출되는 이벤트- css에서 가상키보드 높이 값을
env(keyoard-inset-height)
로 사용 가능
이런식으로 작동하면 좋겠다(행복회로)
- 여기부터는 Bramus가 원하는 바
- 문제1: 자바스크립트를 쓰지않고 처음부터 동작을 정의하면 좋겠다.
- 아래 처럼 메타 태그가 적절할 듯
<meta name="viewport" content="width=device-width, initial-scale=1.0, virtual-keyboard=overlays-content"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, virtual-keyboard=resize-layout"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, virtual-keyboard=resize-visual"/>
<meta name="virtual-keyboard" content="overlays-content"/>
<meta name="virtual-keyboard" content="resize-layout"/>
<meta name="virtual-keyboard" content="resize-visual"/>
- 개발자가 원하는 방식을 정의할 수 있는 방향이면 좋을 것 같다.
- 이 스펙은 지원되는 건 아니고 일단은 그냥 Bramus 개인적인 바람이다.
- 문제2: Layout Viewport크기가 그대로인 iOS 사파리 동작 방식에서 가상키보드 위쪽에 뭔가 위치하게 하고 싶다면?
position: fixed / {viewport}
어떤 Viewport를 기준으로 fixed
할것인지 정할 수 있게 하면 어떨까? 라는 의견.- 아직 논의 중 https://github.com/w3c/csswg-drafts/issues/7475
Viewport investigation effort
Credits